APP_INITIALIZER in Angular

What is an APP_INITIALIZER?

The APP_INITIALIZER is a built in injection token available in angular. The purpose of APP_INITIALIZER is to perform any initialization task when the application loads.

Mostly the APP_INITIALIZER will be used to get the application's configuration details before the application is rendered by called the api. The best way to use it is by returning a promise function, so that it will wait until any operation is done and the promise is resolved. Once the promise is resolved, then the application will be initialized.

Create a new angular project

Create a new angular application using angular cli command.

ng new angular-tutorial

Create a ConfigService

Create a service to hold the configuration details. Lets create the service in the services folder by the following angular cli command.

ng g s services/config

Open the config.service.ts file and modify the code as below.

import { Injectable } from '@angular/core';

@Injectable({
  providedIn: 'root'
})

interface IConfig {
  serverUrl: string;
}
export class ConfigService {


  private config: IConfig = { serverUrl: '' };
  constructor() { }

  init(serverUrl: string) {
    this.config.serverUrl = serverUrl;
    console.log('Configuration has been set.');
  }

  getConfig() {
    return this.config;
  }
}

We have created a variable config which will be holding the property serverUrl. The init() function is used to set the serverUrl property and once the property has been set, then it will log Configuration has been set. to the console.

The getConfig() function is used to return the configuration in the config variable.

Add APP_INITIALIZER in AppModule

Open the app.module.ts file and modify the code as below.

import { BrowserModule } from '@angular/platform-browser';
import { HttpClientModule, HttpClient } from '@angular/common/http';
import { NgModule } from '@angular/core';
import { AppRoutingModule } from './app-routing-module';
import { AppComponent } from './app.component';
import { APP_INITIALIZER } from '@angular/core';
import { ConfigService } from './services/config.service';

const initializeConfig = (configService: ConfigService, http: HttpClient) => {
  return (): Promise<any> => {
    return new Promise((resolve, reject) => {
      http.get('https://reqres.in/api/users/2').toPromise()
        .then((result: any) => {
          console.log(result);
          configService.init(result.ad.url);
          return resolve('Success');
        });
    });
  }
};

@NgModule({
  declarations: [
    AppComponent,
  ],
  imports: [
    AppRoutingModule,
    HttpClientModule,
  ],
  providers: [ConfigService,
    { provide: APP_INITIALIZER, useFactory: initializeConfig, deps: [ConfigService, HttpClient], multi: true }
  ],
  bootstrap: [AppComponent]
})
export class AppModule { }

In the above code we have imported the APP_INITIALIZER and the ConfigService.

In order to use the APP_INITIALIZER, we have to use the syntax as below.

{ provide: APP_INITIALIZER, useFactory: function, deps: [], multi: true/false }

The APP_INITIALIZER as the value to the provide property.

The useFactory property will take function as its value. The function can perform synchronous or asynchronous function.

The deps property is an array that will hold the dependencies needed for the function and the multi parameter can be true or false.

By default it is false. If it is set to false, then we use a token more than once, the last to register will override all the previous tokens. i.e you can have only one provider for token.

If it is true, then the new providers are added to the previously registered providers making it more than one provider for a token. The angular will execute all of them when the token in invoked.

In our code, we have provided intializeConfig() function as the value to useFactory parameter and provided ConfigService and HttpClient as the dependencies in deps array and set the multi parameter to be true.

Next, lets take a look at the initializeConfig function

const initializeConfig = (configService: ConfigService, http: HttpClient) => {
  return (): Promise<any> => {
    return new Promise((resolve, reject) => {
      http.get('https://reqres.in/api/users/2').toPromise()
        .then((result: any) => {
          console.log(result);
          configService.init(result.ad.url);
          return resolve('Success');
        });
    });
  }
};

The initializeConfig() function takes ConfigService and HttpClient as parameter in configService and http variable name respectively.

The initializeConfig() function is going to return a function as result and that function is going to return a Promise.

Inside the function we make api call using http variable and chain it to return it as promise using toPromise.

Retrieve the value returned by promise and call the init() function of ConfigService to set the config. Then return a resolve with a Success message.

Adding some log in AppComponent

Next, open the app.component.ts file and inside its constructor add some console to verify that the APP_INITIALIZER has been loaded initially.

import { Component, OnInit } from '@angular/core';

@Component({
  selector: 'app-root',
  templateUrl: './app.component.html',
  styleUrls: ['./app.component.css'],
})
export class AppComponent implements OnInit {

  constructor() {
    console.log('App component loaded');
  }
  ngOnInit(): void {
  }
}

Run your application using

ng serve --o

Press F12 and check out the console. It will make the api to log the result to the console. It displays logs as below

Configuration has been set.
App component loaded

Most Read